package expression;

import runtime.TypeFactory;
import util.Result;
import util.Scope;
import util.Type;
import exception.ExpressionException;
import exception.TypeException;

/**
 * Klasa odpowiedzialna za przetrzymywanie wyrazenia unarnego
 * 
 * @author Jakub Fibinger
 *
 */
public class UnaryExpression extends Expression {
	
	/**
	 * Wyrazenie nizszego poziomu
	 */
	private Expression expression;
	/**
	 * Znak unarny (minus lub plus) badz informacja o jego braku
	 */
	private Sign sign;
	
	public static enum Sign {
		PLUS,
		MINUS,
		NONE;
	}
	
	/**
	 * @param scope Zakres zmiennych
	 * @param expression Wyrazenie nizszego poziomu
	 * @param sign Znak unarny
	 * @throws ExpressionException
	 */
	public UnaryExpression(Scope scope, Expression expression, Sign sign) throws ExpressionException {
		Type type;
		if (expression == null || sign == null) {
			throw new ExpressionException();
		}
		try {
			TypeFactory tf = TypeFactory.getInstance();
			//System.out.println(expression);
			type = expression.getResultType();
			//System.out.println(type);
			if((sign != Sign.NONE) && !(type.equals(tf.getType("int")) || type.equals(tf.getType("double")))) {
				throw new ExpressionException();
			}
			this.expression = expression;
			result = new Result(type, null);
			this.sign = sign;
		} catch (TypeException e) {
			// zignoruj
		}
	}
	
	/* (non-Javadoc)
	 * @see expression.Expression#evaluate()
	 */
	@Override
	public Result evaluate() throws ExpressionException {
		Type type = this.result.getType();
		try {
			TypeFactory tf = TypeFactory.getInstance();
			if(type.equals(tf.getType("int")) && (this.sign==Sign.MINUS) ) {
				result.setValue(-((Integer)expression.evaluate().getValue()));
			} else if(type.equals(tf.getType("double")) && (this.sign==Sign.MINUS) ) {
				result.setValue(-((Double)expression.evaluate().getValue()));
			} else {
				result.setValue(expression.evaluate().getValue());
			}
			
			return result;
		} catch (TypeException e) {
			// zignoruj
		}
		return null;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString(){
		return "Unary [ sign: " + sign + ", " + expression + "]";
	}

}
